package com.psedu.exam.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.psedu.base.api.RemoteSemesterService;
import com.psedu.base.api.domain.dto.SemesterTrainObjectDTO;
import com.psedu.base.api.domain.dto.StudentDTO;
import com.psedu.exam.constant.Constants;
import com.psedu.exam.domain.*;
import com.psedu.exam.domain.vo.PaperExam;
import com.psedu.exam.domain.vo.PaperVo;
import com.psedu.exam.domain.vo.QuestionDetail;
import com.psedu.exam.domain.vo.QuestionVo;
import com.psedu.exam.mapper.AnswerSheetMapper;
import com.psedu.exam.mapper.PaperQuestionMapper;
import com.psedu.exam.mapper.QuestionMapper;
import com.psedu.exam.service.IQuestionService;
import com.psedu.exam.utils.QuestionUtils;
import com.psedu.common.core.constant.SecurityConstants;
import com.psedu.common.core.domain.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.psedu.exam.mapper.PaperMapper;
import com.psedu.exam.service.IPaperService;

/**
 * 试卷Service业务层处理
 * 
 * @author mingyue
 * @date 2022-03-30
 */
@Service
public class PaperServiceImpl implements IPaperService 
{
    @Autowired
    private PaperMapper paperMapper;

    @Autowired
    private PaperQuestionMapper paperQuestionMapper;

    @Autowired
    private IQuestionService questionService;

    @Autowired
    private RemoteSemesterService remoteSemesterService;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private IPaperService paperService;

    @Autowired
    private AnswerSheetMapper answerSheetMapper;

    /**
     * 查询试卷
     * 
     * @param paperId 试卷主键
     * @return 试卷
     */
    @Override
    public Paper selectPaperByPaperId(Long paperId)
    {
        return paperMapper.selectPaperByPaperId(paperId);
    }

    /**
     * 查询试卷列表
     * 
     * @param paper 试卷
     * @return 试卷
     */
    @Override
    public List<Paper> selectPaperList(Paper paper)
    {
        return paperMapper.selectPaperList(paper);
    }

    /**
     * 新增试卷
     * 
     * @param paper 试卷
     * @return 结果
     */
    @Override
    public int insertPaper(Paper paper)
    {
        return paperMapper.insertPaper(paper);
    }

    /**
     * 修改试卷
     * 
     * @param paper 试卷
     * @return 结果
     */
    @Override
    public int updatePaper(Paper paper)
    {
        return paperMapper.updatePaper(paper);
    }

    /**
     * 批量删除试卷
     * 
     * @param paperIds 需要删除的试卷主键
     * @return 结果
     */
    @Override
    public int deletePaperByPaperIds(Long[] paperIds)
    {
        return paperMapper.deletePaperByPaperIds(paperIds);
    }

    /**
     * 删除试卷信息
     * 
     * @param paperId 试卷主键
     * @return 结果
     */
    @Override
    public int deletePaperByPaperId(Long paperId)
    {
        return paperMapper.deletePaperByPaperId(paperId);
    }

    @Override
    public Paper recordPaperProblem(PaperExam paperExam, PaperVo paperVo) {
        // 记录试卷
        long judgeQuestionCount = paperVo.getJudgeQuestionDetailList().size();
        long singleQuestionCount = paperVo.getSingleQuestionDetailList().size();
        long multiQuestionCount = paperVo.getMultiQuestionDetailList().size();
        Paper paper = new Paper();
        paper.setExamId(paperExam.getExamId());
        paper.setRadioCount(singleQuestionCount);
        paper.setJudgeCount(judgeQuestionCount);
        paper.setMultipleCount(multiQuestionCount);
        paper.setFillCount(0L);
        paper.setSaqCount(0L);
        paper.setRepeatCount(paperExam.getRepeatCount());
        paperMapper.insertPaper(paper);
        // 记录题目
        List<QuestionDetail> allQuestionDetail = paperVo.getAllQuestionDetail();
        List<Long> questionIds = allQuestionDetail.stream()
                .map(QuestionDetail::getQuestionId)
                .collect(Collectors.toList());
        Map<Long, List<Long>> correctAnswerMap = questionService.getCorrectAnswer(questionIds);
        List<PaperQuestion> paperQuestionList = allQuestionDetail.stream()
                .map(convertQuestionDetail2PaperQuestionFunction(paper, correctAnswerMap)).collect(Collectors.toList());
        paperQuestionMapper.insertBatch(paperQuestionList);
        return paper;
    }

    public PaperVo createExamPaper(ExamDeptStatus examDeptStatus, Long examId, Exam exam, Long semeId, StudentDTO studentDto) {
        PaperVo paperVo = new PaperVo();
        R<SemesterTrainObjectDTO> examTrainObjectR =
                remoteSemesterService.getTrainObjectBySemesterId(semeId, SecurityConstants.INNER);
        SemesterTrainObjectDTO semesterTrainObject = examTrainObjectR.getData();
        Integer trainObject = semesterTrainObject.getTrainObject();
        paperVo.setExamName(exam.getExamName());
        paperVo.setStartTime(examDeptStatus.getStartTime());
        paperVo.setEndTime(examDeptStatus.getStartTime());
        // 获取随机题目
        createPaperProblem(paperVo, trainObject);
        // 记录题目
        PaperExam paperExam = new PaperExam();
        paperExam.setExamId(examId);
        paperExam.setRepeatCount(examDeptStatus.getRepeatCount());
        Paper paper = paperService.recordPaperProblem(paperExam, paperVo);
        // 创建答卷
        AnswerSheet newAnswerSheet = new AnswerSheet();
        newAnswerSheet.setApplyId(studentDto.getApplyId());
        newAnswerSheet.setSemeId(semeId);
        newAnswerSheet.setRepeatCount(examDeptStatus.getRepeatCount());
        newAnswerSheet.setPaperId(paper.getPaperId());
        newAnswerSheet.setStatus(Constants.ANSWER_SHEET_IN_USE);
        newAnswerSheet.setOfficialExam(exam.getOfficialExam());
        answerSheetMapper.insert(newAnswerSheet);
        return paperVo;
    }

    public void createPaperProblem(PaperVo paperVo, Integer trainObject) {
        // 单选
        List<QuestionVo> singleQuestions = questionMapper.selectRandomQuestionDetail(
                trainObject,
                Constants.SINGLE_COUNT,
                Constants.SINGLE_QUESTION
        );
        List<QuestionDetail> singleQuestionDetailList = QuestionUtils.convertQuestionDetail(singleQuestions);
        paperVo.setSingleQuestionDetailList(singleQuestionDetailList);
        // 判断
        List<QuestionVo> judgeQuestions = questionMapper.selectRandomQuestionDetail(
                trainObject,
                Constants.JUDGE_COUNT,
                Constants.JUDGE_QUESTION
        );
        List<QuestionDetail> judgeQuestionDetailList = QuestionUtils.convertQuestionDetail(judgeQuestions);
        paperVo.setJudgeQuestionDetailList(judgeQuestionDetailList);
        // 多选
        List<QuestionVo> multiQuestions = questionMapper.selectRandomQuestionDetail(
                trainObject,
                Constants.MULTI_COUNT,
                Constants.MULTI_QUESTION
        );
        List<QuestionDetail> multiQuestionDetailList = QuestionUtils.convertQuestionDetail(multiQuestions);
        paperVo.setMultiQuestionDetailList(multiQuestionDetailList);
    }

    @Override
    public PaperVo getPaperVoByPaperId(Paper paper) {
        PaperVo paperVo = new PaperVo();
        // 通过paperId获取所有的questionId
        Long paperId = paper.getPaperId();
        List<PaperQuestion> paperQuestions = paperQuestionMapper.selectList(
                new LambdaQueryWrapper<PaperQuestion>()
                        .eq(PaperQuestion::getPaperId, paperId)
        );
        List<Long> questionIds = paperQuestions.stream().map(PaperQuestion::getQuestionId).collect(Collectors.toList());
        List<QuestionVo> questionVos = questionMapper.selectQuestionDetail(questionIds);
        // 获取questionId获取所有的选项
        // 单选
        List<QuestionVo> singleQuestionVoList = questionVos.stream()
                .filter(questionVo -> questionVo.getType() == Constants.SINGLE_QUESTION)
                .collect(Collectors.toList());
        paperVo.setSingleQuestionDetailList(QuestionUtils.convertQuestionDetail(singleQuestionVoList));
        // 判断
        List<QuestionVo> judgeQuestionVoList = questionVos.stream()
                .filter(questionVo -> questionVo.getType() == Constants.JUDGE_QUESTION)
                .collect(Collectors.toList());
        paperVo.setJudgeQuestionDetailList(QuestionUtils.convertQuestionDetail(judgeQuestionVoList));
        // 多选
        List<QuestionVo> multiQuestionVoList = questionVos.stream()
                .filter(questionVo -> questionVo.getType() == Constants.MULTI_QUESTION)
                .collect(Collectors.toList());
        paperVo.setMultiQuestionDetailList(QuestionUtils.convertQuestionDetail(multiQuestionVoList));
        return paperVo;
    }

    private Function<QuestionDetail, PaperQuestion> convertQuestionDetail2PaperQuestionFunction(Paper paper,
                                                                                                Map<Long, List<Long>> correctAnswerMap) {
        return questionDetail -> {
            PaperQuestion paperQuestion = new PaperQuestion();
            paperQuestion.setPaperId(paper.getPaperId());
            paperQuestion.setQuestionId(questionDetail.getQuestionId());
            paperQuestion.setContent(questionDetail.getContent());
            paperQuestion.setAnalysis("");
            paperQuestion.setType(questionDetail.getType());
            paperQuestion.setScore(questionType2Score(questionDetail.getType()));
            List<Long> correctOptionIds = correctAnswerMap.getOrDefault(questionDetail.getQuestionId(), new ArrayList<>());
            // 正确选项 ABCD
            List<QuestionDetail.AnswerOption> optionList = questionDetail.getOptionList();
            StringBuffer correctAnswerStr = new StringBuffer();
            char[] letterAnswer = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
            for (int i = 0; i < optionList.size(); i++) {
                Long optionId = questionDetail.getOptionIdByIndex(i);
                if(correctOptionIds.contains(optionId)) {
                    correctAnswerStr.append(letterAnswer[i]);
                }
            }
            paperQuestion.setAnswer(correctAnswerStr.toString());
            // 选项
            paperQuestion.setOptionA(questionDetail.getOptionContentByIndex(0));
            paperQuestion.setOptionB(questionDetail.getOptionContentByIndex(1));
            paperQuestion.setOptionC(questionDetail.getOptionContentByIndex(2));
            paperQuestion.setOptionD(questionDetail.getOptionContentByIndex(3));
            paperQuestion.setOptionE(questionDetail.getOptionContentByIndex(4));
            paperQuestion.setOptionF(questionDetail.getOptionContentByIndex(5));
            paperQuestion.setRemark("");
            return paperQuestion;
        };
    }

    public int questionType2Score(int type) {
        if(Constants.SINGLE_QUESTION == type) {
            return Constants.SINGLE_PER_SCORE;
        } else if(Constants.JUDGE_QUESTION == type) {
            return Constants.JUDGE_PER_SCORE;
        } else if(Constants.MULTI_QUESTION == type) {
            return Constants.MULTI_PER_SCORE;
        }
        return 0;
    }
}
